home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Programming / QuakeTools / src / libqtools / pak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  7.2 KB  |  286 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3.  
  4. /*
  5.  * PAK-tools
  6.  *
  7.  * entryName    == 0  -> OP_EXTRACT all
  8.  * destDir == 0  -> OP_EXTRACT to current directory
  9.  */
  10.  
  11. /*
  12.  *
  13.  */
  14.  
  15. bool CheckPAK(FILE * pakFile, struct packheader *Header, bool newWad)
  16. {
  17.   if (pakFile) {
  18.     fseek(pakFile, 0, SEEK_END);
  19.     if (ftell(pakFile) == 0) {
  20.       if (newWad == TRUE) {
  21.     /*
  22.      * file is new 
  23.      */
  24.     Header->magic.integer = MAGIC_PACK;
  25.     Header->offset = LittleLong(sizeof(struct packheader));
  26.     Header->size = LittleLong(0);
  27.     fwrite(Header, 1, sizeof(struct packheader), pakFile);
  28.     return TRUE;
  29.       }
  30.       else
  31.     return FALSE;
  32.     }
  33.     else {
  34.       fseek(pakFile, 0, SEEK_SET);
  35.       fread(Header, 1, sizeof(struct packheader), pakFile);
  36.  
  37.       if (Header->magic.integer == MAGIC_PACK) {
  38.         /*
  39.          * file is not a packfile 
  40.          */
  41.     return TRUE;
  42.       }
  43.       else
  44.     return FALSE;
  45.     }
  46.   }
  47.   else
  48.     return FALSE;
  49. }
  50.  
  51. /*
  52.  * findpak return ever one entry more than exists!
  53.  */
  54. struct packentry *FindPAK(FILE * pakFile, char *entryName, struct packheader *Header, struct packentry **Entry)
  55. {
  56.   struct packentry *allEntries;
  57.  
  58.   fseek(pakFile, LittleLong(Header->offset), SEEK_SET);
  59.   if ((*Entry = allEntries = (struct packentry *)tmalloc(LittleLong(Header->size) + sizeof(struct packentry)))) {
  60.     int i;
  61.  
  62.     fread(allEntries, 1, LittleLong(Header->size), pakFile);
  63.     if (entryName) {
  64.       for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
  65.         if (!strncasecmp(entryName, allEntries->name, NAMELEN_PAK)) {
  66.       /*
  67.        * return offset of valid entry 
  68.        */
  69.       return allEntries;
  70.         }
  71.         allEntries++;
  72.       }
  73.     }
  74.     /*
  75.      * not in pakfile 
  76.      */
  77.     return 0;
  78.   }
  79.   else
  80.     return (struct packentry *)-1;
  81. }
  82.  
  83. struct packentry *SearchPAK(char *entryName, struct packheader *Header, struct packentry *allEntries) {
  84.   int i;
  85.  
  86.   for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
  87.     if (!strncasecmp(entryName, allEntries->name, NAMELEN_PAK))
  88.       return allEntries;
  89.     allEntries++;
  90.   }
  91.   return 0;
  92. }
  93.  
  94. bool ExtractPAK(FILE * pakFile, FILE * script, char *destDir, char *entryName, unsigned char outType, operation procOper, bool recurse)
  95. {
  96.   struct packheader Header;
  97.   struct packentry *Entry, *allEntries;
  98.   bool retval = FALSE;
  99.  
  100.   if (CheckPAK(pakFile, &Header, FALSE) == TRUE) {
  101.     /*
  102.      * we assume that the dir is at the end of the file!!!!! 
  103.      */
  104.     switch ((int)(Entry = FindPAK(pakFile, entryName, &Header, &allEntries))) {
  105.       case -1:
  106.     eprintf("cannot tmalloc memory for all entries of size %ld\n", LittleLong(Header.size) + sizeof(struct packentry));
  107.     break;
  108.       case 0:
  109.         if((entryName) && (*entryName != '\0')) {
  110.           eprintf("no entry %s found in pak\n", entryName);
  111.           break;
  112.         }
  113.       default:{
  114.       int i = 0;
  115.  
  116.       /*
  117.        * process only ONE (case 0:)
  118.        */
  119.       if (Entry)
  120.         i = (LittleLong(Header.size) / sizeof(struct packentry)) - 1;
  121.       /*
  122.        * reset and process ALL (default:)
  123.        */
  124.       else
  125.         Entry = allEntries;
  126.  
  127.       for (; i < (LittleLong(Header.size) / sizeof(struct packentry)); i++) {
  128.         char fileName[NAMELEN_PATH];
  129.  
  130.         strncpy(fileName, destDir, NAMELEN_PATH - 1);
  131.         strncat(fileName, Entry->name, NAMELEN_PATH - 1);
  132.  
  133.         switch (procOper) {
  134.           case OP_EXTRACT:{
  135.           FILE *fileDst;
  136.  
  137.           mprintf("extract %s ...\n", Entry->name);
  138.           CreatePath(fileName);
  139.  
  140.           if ((fileDst = fopen(fileName, WRITE_BINARY))) {
  141.             struct rawdata *rawData;
  142.  
  143.             fseek(pakFile, LittleLong(Entry->offset), SEEK_SET);
  144.             if ((rawData = GetRaw(pakFile, Entry->name, LittleLong(Entry->size)))) {
  145.               retval = PutRaw(fileDst, rawData);
  146.               rfree(rawData);
  147.             /*
  148.              * processName at this point
  149.              */
  150.               if (recurse == TRUE)
  151.             retval = processName(fileName, 0, 0, outType, 0, 0, procOper, script ? TRUE : FALSE, recurse);
  152.             }
  153.             else
  154.               eprintf("cannot tmalloc memory for %s of size %d\n", fileName, LittleLong(Entry->size));
  155.             fclose(fileDst);
  156.           }
  157.           else
  158.             eprintf("cannot open %s\n", fileName);
  159.         }
  160.         break;
  161.           case OP_LIST:
  162.           case OP_DEFAULT:
  163.           default:{
  164.           mprintf("%54s %8d bytes (offset: %8x)\n", Entry->name, LittleLong(Entry->size), LittleLong(Entry->offset));
  165.           retval = TRUE;
  166.         }
  167.         break;
  168.         }
  169.         if (script)
  170.           fprintf(script, "update %s as %s as %c\n", fileName, Entry->name, 'P');
  171.         Entry++;
  172.       }
  173.     }
  174.     break;
  175.     }
  176.     tfree(allEntries);
  177.   }
  178.   else
  179.     eprintf("no valid pakfile\n");
  180.  
  181.   return retval;
  182. }
  183.  
  184. bool AddPAK(struct palpic *inPic, struct rawdata * inData, char *pakName, operation procOper)
  185. {
  186.   char *procName;
  187.   FILE *pakFile = fopen(pakName, READWRITE_BINARY_OLD);
  188.   struct packheader Header;
  189.   struct packentry *Entry, *allEntries;
  190.   bool retval = FALSE;
  191.  
  192.   if (!pakFile)
  193.     pakFile = fopen(pakName, READWRITE_BINARY_NEW);
  194.  
  195.   if (pakFile) {
  196.     if (CheckPAK(pakFile, &Header, TRUE) == TRUE) {
  197.       if (inPic) {
  198.     procName = inPic->name;
  199.     ReplaceExt(procName, "lmp");
  200.       }
  201.       else if (inData) {
  202.     procName = inData->name;
  203.       }
  204.       /*
  205.        * we assume that the dir is at the end of the file!!!!! 
  206.        */
  207.       switch ((int)(Entry = FindPAK(pakFile, procName, &Header, &allEntries))) {
  208.     case -1:
  209.       eprintf("cannot tmalloc memory for all entries of size %ld\n", LittleLong(Header.size) + sizeof(struct packentry));
  210.       break;
  211.     case 0:
  212.       switch (procOper) {
  213.         case OP_REPLACE:
  214.           eprintf("no entry %s found to replace in pak %s\n", procName, pakName);
  215.           break;
  216.         case OP_ADD:
  217.         case OP_UPDATE:
  218.         case OP_DEFAULT:
  219.         default:
  220.           fseek(pakFile, LittleLong(Header.offset), SEEK_SET);
  221.           /*
  222.            * seek to end of data 
  223.            */
  224.           Entry = allEntries + (LittleLong(Header.size) / sizeof(struct packentry));
  225.           Entry->offset = Header.offset;
  226.  
  227.           if (inData)
  228.             retval = PutRaw(pakFile, inData);
  229.           else if (inPic)
  230.             retval = PutLMP(pakFile, inPic);
  231.           else
  232.             eprintf("nothing to add\n");
  233.  
  234.           if(retval == TRUE) {
  235.             Entry->size = LittleLong(ftell(pakFile) - LittleLong(Header.offset));
  236.             strncpy(Entry->name, procName, NAMELEN_PAK);
  237.             Header.size = LittleLong(LittleLong(Header.size) + sizeof(struct packentry));
  238.             Header.offset = LittleLong(ftell(pakFile));
  239.             /*
  240.              * write directory
  241.              */
  242.             if(fwrite(allEntries, 1, LittleLong(Header.size), pakFile) == LittleLong(Header.size)) {
  243.               fseek(pakFile, 0, SEEK_SET);
  244.               /*
  245.                * write header
  246.                */
  247.               fwrite(&Header, 1, sizeof(struct packheader), pakFile);
  248.               fflush(pakFile);
  249.             }
  250.             else
  251.               retval = FALSE;
  252.           }
  253.           else
  254.             eprintf("cannot write data %s to pak %s\n", procName, pakName);
  255.           break;
  256.       }
  257.       tfree(allEntries);
  258.       break;
  259.     default:
  260.       switch (procOper) {
  261.         case OP_REPLACE:
  262.         case OP_UPDATE:
  263.           /* DeletePAK() */
  264.           /* AddPAK() */
  265.           retval = TRUE;
  266.           break;
  267.         case OP_ADD:
  268.         case OP_DEFAULT:
  269.         default:
  270.           eprintf("old entry %s found in pak %s\n", procName, pakName);
  271.           break;
  272.       }
  273.       tfree(allEntries);
  274.       break;
  275.       }
  276.       fclose(pakFile);
  277.     }
  278.     else
  279.       eprintf("no valid pakfile %s\n", pakName);
  280.   }
  281.   else
  282.     eprintf("cannot open desired pakfile %s\n", pakName);
  283.     
  284.   return retval;
  285. }
  286.